#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/wait.h>

#define TIME_RESET 1800

static volatile int flag_exit = 0;
static pid_t pid_child = 0;

static void sig_exit(int s)
{
    printf("%s() in\n", __FUNCTION__);
    flag_exit = 1;
}

/** 用于定时重置子进程 */
static void* thread_kill(void *unused)
{
    unsigned int seconds_left = TIME_RESET; // 未走完的秒数

    while (!flag_exit)
    {
	while ((seconds_left = sleep(seconds_left)) && (!flag_exit)); // 坚持走完 seconds_left 秒
	printf("kill pid = %d\n", pid_child);
	if ((!flag_exit) && kill(pid_child, SIGQUIT))
	{
	    fprintf(stderr, "[WARNING] kill pid %d failed: %s\n", pid_child, strerror(errno));
	}
	seconds_left = TIME_RESET;
    }
    printf("thread_kill exit.\n");
    pthread_exit(NULL);
}

static void abort_clean(pid_t pid)
{
    printf("abort pid = %d\n", pid);
    kill(pid, SIGINT);
    wait(NULL);
}

int main(int argc, char **argv)
{
      int result = 0;
      int flag_first_init = 1;
      pid_t pid;
      pthread_t tid;

      if (argc < 3)
      {
	  fprintf(stderr, "Usage: %s <RepoPath> <SourcePath>\n", argv[0]);
	  exit(1);
      }

      while (!flag_exit)
      {
	  pid_child = pid = fork();
	  if (pid < 0)
	  {
	      perror("ERROR: fork()");
	      exit(1);
	  }
	  else if (pid > 0) // parent
	  {
	      printf("create pid = %d\n", pid);
	      if (flag_first_init) {
		  flag_first_init = 0;
		  if (SIG_ERR == signal(SIGINT, sig_exit))
		  {
		      abort_clean(pid);
		      perror("signal SIGINT");
		      exit(1);
		  }

		  if (pthread_create(&tid, NULL, thread_kill, NULL))
		  {
		      abort_clean(pid);
		      perror("pthread_create()");
		      exit(1);
		  }
	      }

	      wait(&result);
	      printf("[%lld] result = %d\n", (long long) pid, result);
	      if (0 == result) // Normal exit
	      {
		      flag_exit = 1;
		      break;
	      }
	  }
	  else // child
	  {
	      if (chdir(argv[2]) < 0)
	      {
		  perror("ERROR: chdir()");
		  exit(1);
	      }
	      if (execl(argv[1], "repo", "sync", NULL))
	      {
		  perror("ERROR: execl()");
		  exit(1);
	      }
	  }
      }
      pthread_join(tid, NULL);
      return 0;
}
